package com.sq.partner.manager.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import com.sq.partner.manager.common.exception.AppException;
import com.sq.partner.manager.dao.GatewayEinvoiceDao;
import com.sq.partner.manager.mybatis.model.EinvoiceDto;
import com.sq.partner.manager.mybatis.model.GatewayEinvoice;
import com.sq.partner.manager.mybatis.model.GatewayUser;
import com.sq.partner.manager.mybatis.model.TradAgentInfo;
import com.sq.partner.manager.util.ExcelUtil;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.stereotype.Service;

import com.sq.partner.manager.common.Config;
import com.sq.partner.manager.common.Constants;
import com.sq.partner.manager.dao.IGatewayChannelInfoConfigDao;
import com.sq.partner.manager.dao.IPushInfoManagerDao;
import com.sq.partner.manager.mybatis.model.CoreDept;
import com.sq.partner.manager.mybatis.model.GatewayChannelInfo;
import com.sq.partner.manager.mybatis.model.TGatewayInvoice;
import com.sq.partner.manager.service.IPushInfoManagerService;
import com.sq.partner.manager.util.FreeMarkerUtil;
import com.sq.partner.manager.util.HttpConnectorUtil;
import com.sq.partner.manager.util.LogUtil;
import com.sq.partner.manager.util.Page;
import org.springframework.web.multipart.MultipartFile;

@Service
public class PushInfoManagerServiceImpl implements IPushInfoManagerService {
    private static Logger logger = LogUtil.getLog(PushInfoManagerServiceImpl.class);
	@Resource
	IPushInfoManagerDao pushInfoManagerDao;
	
	@Resource
	private IGatewayChannelInfoConfigDao channelInfoConfigDao;

	@Resource
	private GatewayEinvoiceDao gatewayEinvoiceDao;
	
	
	@Override
	public Page<GatewayChannelInfo> queryChannelInfoPage(Page<GatewayChannelInfo> page) throws Exception {
		return channelInfoConfigDao.queryChannelInfoPageOfLife(page);
	}
	
	@Override
	public Page queryInviocePageByCriteria(Page page) throws Exception {

		return pushInfoManagerDao.queryInviocePageByCriteria(page);
	}

	@Override
	public boolean editInvioceGroup(TGatewayInvoice tGatewayInvoice)throws Exception {
		
		return pushInfoManagerDao.editInvioceGroup(tGatewayInvoice);
	}
	
	@Override
	public List<Map<String, Object>> beforePushInvioce(Map<String, Object> map)throws Exception {
		return pushInfoManagerDao.beforePushInvioce(map);
	}

	@Override
	public List<Map<Object, Object>> queryInvioceByID(Map<String, Object> map)throws Exception {
		List<Map<Object, Object>> resultList = new ArrayList<Map<Object,Object>>();
		List<Map<String, Object>> InvioceList = pushInfoManagerDao.queryInvioceByID(map);
		for (int i = 0; i < InvioceList.size(); i++) {
			Map<Object, Object> resultMap =new HashMap<Object,Object>();
			String xml="";
			String responseXml = "";
			String polNo = "";
			for (String key : InvioceList.get(i).keySet()) {
				if("POLNO".equals(key)){					//保单号
					polNo = (String)InvioceList.get(i).get(key);
				}
			}
			xml=FreeMarkerUtil.process("/app/pgroup/PS014.ftl", InvioceList.get(i));//查询交易系统保单时需要的参数
			logger.debug("查询交易系统的报文:"+xml);
			responseXml=HttpConnectorUtil.interaction(Config.getProp("pgroup.pushInvoice.url"), xml,"",Constants.GW_CH_TX_PS014);//从交易系统查询保单信息
			logger.info("查询保单号："+polNo);
			logger.debug("交易系统返回报文"+responseXml);
			Document doucument = DocumentHelper.parseText(responseXml);
			Element element = doucument.getRootElement();
			///2.3解析报文校验查询是否成功
			String resultCodePS014 = selectSingleNodeByRoot(element , "/INSUREQRET/HEAD/RESULTCODE");
			TGatewayInvoice tGatewayInvoice = new TGatewayInvoice();
			tGatewayInvoice.setID(Integer.parseInt(InvioceList.get(i).get("ID")+""));
			if("0000".equals(resultCodePS014)){
				resultMap.put(polNo, "推送成功");
				tGatewayInvoice.setStatus("2");
			}else{
				String ERRINFO = selectSingleNodeByRoot(element , "/INSUREQRET/HEAD/ERRINFO");
				resultMap.put(polNo, "推送失败，失败原因为:"+ERRINFO);
				tGatewayInvoice.setStatus("3");
			}
			editInvioceGroup(tGatewayInvoice);//修改推送状态
			resultList.add(resultMap);
		}
		
		return resultList;
	}
	
	 public String selectSingleNodeByRoot(Element root,String path){
		 Node node = root.selectSingleNode(path);
		 if(node==null){
			 return "";
		 }else{
			 return node.getText();
		 }
	 }

	@Override
	public Map<String, String> queryIsPushInvioceBypartnerNo(String partnerNo)throws Exception {
		
		return pushInfoManagerDao.queryIsPushInvioceBypartnerNo(partnerNo);
	}

	@Override
	public List<String> queryUserDept(String userId) throws Exception {
		return pushInfoManagerDao.queryUserDept(userId);
	}
	@Override
	public List<CoreDept> queryPrivilegeBranch(List<String> deptCodeStr)throws Exception {

		return pushInfoManagerDao.queryDeptList(deptCodeStr);
	}

	
	@Override
	public String pushPolicyInfo(String polNo)throws Exception {
		String resultInfo = "";
		Map<String, String> map =new HashMap<String,String>();
		map.put("SERIALNUMBER",getSerialNumberByPolno(polNo));
		map.put("POLNO",polNo);
		String xml="";
		String responseXml = "";
		xml=FreeMarkerUtil.process("/app/pushPolicy/pushPolicy.ftl", map);//查询交易系统保单时需要的参数
		logger.debug("查询交易系统的报文:"+xml);
		responseXml=HttpConnectorUtil.interaction(Config.getProp("push.pushPolicy.url"), xml,"",Constants.GW_CH_TX_2016);//从交易系统查询保单信息
		logger.info("查询保单号："+polNo);
		logger.debug("交易系统返回报文"+responseXml);
		Document doucument = DocumentHelper.parseText(responseXml);
		Element element = doucument.getRootElement();
		///2.3解析报文校验查询是否成功
		String resultCode = selectSingleNodeByRoot(element , "/INSUREQRET/HEAD/RESULTCODE");
		String ERRINFO = selectSingleNodeByRoot(element , "/INSUREQRET/HEAD/ERRINFO");
		if("0000".equals(resultCode)){
			resultInfo = ERRINFO;
		}else{
			resultInfo = "推送失败! 失败原因为:"+ERRINFO;
		}
		return resultInfo;
	}
	
	 public String getSerialNumberByPolno(String polno) throws Exception{
		 SimpleDateFormat si =new SimpleDateFormat("yyyyMMddHHmmssSSS");
		 String code =si.format(new Date());
		return polno+code;
	}

	@Override
	public List<EinvoiceDto> queryEinvoiceByPolList(String[] polNoList) throws Exception {
		String resultInfo = "";
		Map<String, Object> map =new HashMap<String,Object>();
		SimpleDateFormat si =new SimpleDateFormat("yyyyMMddHHmmssSSS");
		String code =si.format(new Date());
		map.put("SERIALNUMBER",code);
		map.put("PolNoList",polNoList);
		String xml="";
		String responseXml = "";
		xml=FreeMarkerUtil.process("/app/pgroup/PS017.ftl", map);//查询交易系统保单时需要的参数
		logger.debug("查询交易系统的报文:"+xml);
		responseXml=HttpConnectorUtil.interaction(Config.getProp("pgroup.pushInvoice.url"), xml,"",Constants.GW_CH_TX_PS017);//从交易系统查询保单信息
		logger.debug("交易系统返回报文"+responseXml);
		Document doucument = DocumentHelper.parseText(responseXml);
		Element root = doucument.getRootElement();
		///2.3解析报文校验查询是否成功
		String resultCode = selectSingleNodeByRoot(root , "/INSUREQ/HEAD/RESULTCODE");
		String ERRINFO = selectSingleNodeByRoot(root , "/INSUREQ/HEAD/ERRINFO");
		List<Element> list = root.selectNodes("/INSUREQ/MAIN/INVOICELIST/INVOICE");
		List<EinvoiceDto> eInvoiceList = new ArrayList<EinvoiceDto>();
		for (Element element : list) {
			Iterator<Element> it = element.elementIterator();
			EinvoiceDto einvoice = new EinvoiceDto();
			while (it.hasNext()) {
				Element next = it.next();
				if ("POLNO".equals(next.getName())){
					einvoice.setPolNo(next.getText());
				}else if ("kprq".equals(next.getName())){
					einvoice.setKprq(next.getText());
				}else if ("fpdm".equals(next.getName())){
					einvoice.setFpdm(next.getText());
				}else if ("fphm".equals(next.getName())){
					einvoice.setFphm(next.getText());
				}else if ("kpje".equals(next.getName())){
					einvoice.setKpje(next.getText());
				}else if ("kjzt".equals(next.getName())){
					//开具状态
					String status = "";
					GatewayEinvoice gatewayEinvoice = gatewayEinvoiceDao.queryeinvoicebypolno(einvoice.getPolNo());
					if (gatewayEinvoice == null){
						status = "3";
					}else {
						status = gatewayEinvoice.getBackStatus();
						status = (status == null) ? "0" : status;
					}
					//根据不同状态显示不同按钮
					einvoiceButton(einvoice,status);
					//根据不同状态显示不同文字
					//einvoice.setKjzt(eInvoiceStata(next.getText()));
					einvoice.setKjzt(eInvoiceStata(status));
				}else if ("URL".equals(next.getName())){
					einvoice.setUrl(next.getText());
				}
			}
			eInvoiceList.add(einvoice);
		}
		return eInvoiceList;
	}

	@Override
	public void rePushByPol(String polNo) throws Exception {
		pushInfoManagerDao.rePushByPol(polNo);
	}

	@Override
	public List<InputStream> getFileInputStream(MultipartFile[] myfiles) throws AppException {
		List<InputStream> inputStreams=new ArrayList<InputStream>();
		try {
			for(MultipartFile file : myfiles){
				String fileNameStr = file.getOriginalFilename();
				int lastDotIndex = fileNameStr.lastIndexOf(".");
				if(-1==lastDotIndex){
					throw new AppException("请选择扩展名为 .xls 的文件上传");
				}else{
					String extName = fileNameStr.substring(lastDotIndex+1,fileNameStr.length());
					if(!"xls".equals(extName.toLowerCase())){
						throw new AppException("请选择扩展名为 .xls 的文件上传");
					}
				}
				if (file.isEmpty()) {
					throw new AppException("上传失败，上传文件不能为空！");
				} else {
					InputStream inputStream = file.getInputStream();
					inputStreams.add(inputStream);
				}
			}
		} catch (IOException e) {
			logger.info("上传错误!请稍后重试",e);
			throw new AppException("上传错误!请稍后重试");
		}
		return inputStreams;
	}


	@Override
	public  List<String> insertPolNoList(InputStream inputStream, GatewayUser user, HttpSession session) throws Exception {
		//一、校验excel数据是否合法;
		HSSFWorkbook workBook = null;
		List<String> list = new ArrayList<String>();
		try{
			workBook = new HSSFWorkbook(inputStream);
		}catch(Exception e){
			logger.info("上传失败，上传文件内容有误",e);
			throw new AppException("上传失败，上传文件内容有误!");
		}
		HSSFSheet sheet = workBook.getSheetAt(0);
		int lastRowNum = sheet.getLastRowNum();
		if (lastRowNum >= 202){
			throw new AppException("一次最多只能查询200条数据");
		}
		for (int rowNum = 2; rowNum <= lastRowNum; rowNum++) {
			HSSFRow row = sheet.getRow(rowNum);
			//去除空行
			if (null == row){
				continue;
			}
			//去除空格并校验是否中文
			String cellText = ExcelUtil.getCellText(row.getCell(0)).trim();
			String regexM = "[A-Za-z0-9_]+";
			if (!cellText.matches(regexM)){
				throw new AppException("第"+(rowNum+1)+"条"+"数据格式不正确（注：正确格式只能录入字母、数字、下划线组合的字符），请检查");
			}
			list.add(cellText);
		}
		return list;
	}

	@Override
	public void rePushByPolList(String polNoList) throws Exception {
		String[] polList = polNoList.split(",");
		List<String> list = Arrays.asList(polList);
		pushInfoManagerDao.rePushByPolList(list);
	}

	private String eInvoiceStata(String kjzt){
		int state = Integer.parseInt(kjzt);
		switch (state){
			case 0:
				kjzt = "待推送";
				break;
			case 1:
				kjzt = "推送成功";
				break;
			case 2:
				kjzt = "推送失败";
				break;
			default:
				kjzt = "无结果";
		}
		return kjzt;
	}

	private void einvoiceButton(EinvoiceDto einvoice,String status) throws SQLException {
		if ("2".equals(status) || "0".equals(status)){
			einvoice.setFirstButton("<input class='input_fxk' name='checkData' id='firstbutton' type='checkBox' value='#'>");
			einvoice.setLastButton("<a href='javascript:void(0)' onClick='rePushByPol(this)'>重新推送</a>");
		}else if ("1".equals(status)){
			einvoice.setLastButton("<a href='javascript:void(0)' onClick='einvoiceInfo(this)'>查看详情</a>");
		}
	}
}
